package com.fanxuankai.boot.upload.dao;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.fanxuankai.boot.upload.Status;
import com.fanxuankai.boot.upload.domain.Job;
import com.fanxuankai.commons.util.DateUtils;

import java.util.Date;
import java.util.List;

/**
 * @author fanxuankai
 */
public interface JobDao extends IService<Job> {
    /**
     * 锁定任务为处理中
     *
     * @param job 任务
     * @return /
     */
    default boolean lock(Job job) {
        Job entity = new Job();
        entity.setStatus(Status.PROCESSING.name());
        entity.setExpectEndTime(DateUtils.plusMillisecond(new Date(), job.getTimeout()));
        return update(entity, Wrappers.lambdaUpdate(Job.class)
                .eq(Job::getId, job.getId())
                .eq(Job::getStatus, Status.UPLOADED.name()));
    }

    /**
     * 处理完成
     *
     * @param id 任务
     * @return /
     */
    default boolean complete(long id) {
        Job entity = new Job();
        entity.setEndTime(new Date());
        entity.setStatus(Status.COMPLETED.name());
        return update(entity, Wrappers.lambdaUpdate(Job.class)
                .eq(Job::getId, id)
                .eq(Job::getStatus, Status.PROCESSING.name()));
    }

    /**
     * 处理失败
     *
     * @param id 任务
     * @return /
     */
    default boolean failed(long id) {
        Job entity = new Job();
        entity.setStatus(Status.FAILED.name());
        return update(entity, Wrappers.lambdaUpdate(Job.class)
                .eq(Job::getId, id)
                .eq(Job::getStatus, Status.PROCESSING.name()));
    }

    /**
     * 查处理超时的任务
     *
     * @return /
     */
    default List<Job> listTimeout() {
        return list(Wrappers.lambdaQuery(Job.class)
                .lt(Job::getExpectEndTime, new Date())
                .eq(Job::getStatus, Status.PROCESSING.name()));
    }

    /**
     * 查待处理的任务
     *
     * @return /
     */
    default List<Job> listUploaded() {
        return list(Wrappers.lambdaQuery(Job.class)
                .eq(Job::getStatus, Status.UPLOADED.name()));
    }

    /**
     * 重置处理超时的任务
     *
     * @param job 任务
     * @return /
     */
    default boolean resetTimeout(Job job) {
        Job entity = new Job();
        entity.setStatus(Status.UPLOADED.name());
        return update(entity, Wrappers.lambdaUpdate(Job.class)
                .eq(Job::getId, job.getId())
                .lt(Job::getExpectEndTime, new Date())
                .eq(Job::getStatus, Status.PROCESSING.name()));
    }

    /**
     * 计算进度
     *
     * @param id 主键
     * @return /
     */
    Float calcProgress(long id);
}
